from google.appengine.ext import db

'''
Created on Jul 23, 2010

@author: Aidamina
'''

from lib.cache import Cache,CachedModel
from lib.session import StatefulHandler 
from lib.entity import Entity
 
class LocalizedText(CachedModel):
    '''
    classdocs
    '''
    owner = db.UserProperty()
    
    def __init__(self, *args, **kwargs):
        super(LocalizedText, self).__init__(*args, **kwargs)
            
    def __getitem__(self, language):
        if type(language) is not Language: 
            raise TypeError(language,Language)
        textValue = Cache.get(self, language, type = LocalizedTextValue)     
        if not textValue and self.values():
            textValue = self.values().filter('language = ', language).get()
            if textValue:
                Cache.set(self, language, value=textValue, type = LocalizedTextValue)
        return textValue

    def __setitem__(self, language,value):
        if type(language) is not Language:
            raise TypeError(language,Language)
        oldValue = None
        if self.values():
            oldValue = self.values().filter('language = ', language).get()
        textValue = LocalizedTextValue(parent=self, owner=self, language=language, value=value)
        textValue.put()
        if oldValue:
            oldValue.owner = textValue
            oldValue.put()
            
    def __delitem__(self, language):
        textValue = self[language]
        if textValue:
            textValue.delete()
    
    def current(self, value=None):
        language = Language.current()
        if value:
            self[language]=value      
        else:
            return self[language]        
            
    def text(self):
        textValue = self.current()
        if textValue:
            return textValue.text()
        return None
    
    def html(self):        
        textValue = self.current()
        if textValue:
            return textValue.html()
        return None
    
    def delete(self):
        if self.values():  
            for value in self.values():
                value.delete()
        super(LocalizedText, self).delete()
    
    def __str__(self):        
        return str(self.text())
    
    def values(self):
        return getattr(self,'_values',None)            
        
    def languages(self):
        if self.values():
            for value in self.values():
                yield value.language

class LocalizedTextProperty(db.ReferenceProperty):
    '''
    classdocs
    '''
        
    def __init__(self, *args, **kwargs):  
        kwargs['reference_class'] = LocalizedText
        super(LocalizedTextProperty, self).__init__(*args, **kwargs)
        
    
    def get_value_for_datastore(self, model_instance):
        
        value =  super(LocalizedTextProperty, self).get_value_for_datastore(model_instance)
        if value:
            self.__get__(model_instance, model_instance.__class__).put()
        return value
    
    def __property_config__(self, model_class, property_name):
        self.collection_name = self.collection_name or '%s_%s_set' % (model_class.__name__.lower(),property_name.lower())
        super(LocalizedTextProperty,self).__property_config__(model_class, property_name)
    
    def _delete(self, model_instance):        
        text = self.__get__(model_instance, LocalizedText)
        if text:
            text.delete()

    def __get__(self, model_instance, model_class):
        text = None
        if model_instance is None:
            return self
        if hasattr(model_instance, super(LocalizedTextProperty, self)._attr_name()):
            reference_id = getattr(model_instance, self._attr_name())
            text = Cache.get(reference_id,type=LocalizedText)
        if not text:
            try:
                text = super(LocalizedTextProperty,self).__get__(model_instance, model_class)
            except db.Error:
                pass
        if not text:
            if model_instance.has_key():                
                text = LocalizedText(parent = model_instance)
                raise text.key()
                text.put()
                super(LocalizedTextProperty,self).__set__(model_instance,text)
                model_instance.put()
            else: 
                raise db.NotSavedError("Can't use LocalizedTextProperty on unsaved object")
        return text
    
    def __set__(self, model_instance, value):
        if not value or isinstance(value, db.Key):
            return super(LocalizedTextProperty, self).__set__(model_instance,value)
        text = self.__get__(model_instance, model_instance.__class__)
        if text:
            text.current(value)
        else:
            raise "Unhandled Exception" 
    
class Language(Entity, CachedModel):
    '''
    classdocs
    '''
    _default = None
    
    locale = db.StringProperty(required = True)
    
    code = db.StringProperty(required = True)
    
    name = LocalizedTextProperty()
    
    @staticmethod
    def current():
        language = None
        key=None
        handler = StatefulHandler.current()        
        if handler:
            key = handler.request.session['language']
        if key:
            language = Language.get(key)
        if not language:
            language = Language.default()
        if not language:
            raise "No language in Language.current()"
        return language
    
    @staticmethod
    def default(language=None):
        if language:
            Language._default = language
        else:
            if not Language._default:
                Language._default = Language.all().get()
            if not Language._default:
                lang = Language(locale="temp",code="temp")
                lang.put() 
                Language._default = lang            
            return Language._default
         
    def __str__(self):
        return str(self.name)
        
    def put(self):
        return super(Language, self).put()
        
    def delete(self):
        super(Language, self).delete()
        
class LocalizedModel(db.Model):
    def __init__(self, *args, **kwargs):
        super(LocalizedModel, self).__init__(*args, **kwargs)
        
    def delete(self):
        props = self.properties()
        for prop in props:
            if props[prop].__class__==LocalizedTextProperty:
                LocalizedTextProperty._delete(props[prop], self)
        super(Entity,self).delete()

class LocalizedTextValue(CachedModel):
    
    owner = db.ReferenceProperty(required = True, collection_name = '_values')    
    
    language = db.ReferenceProperty(Language, required = True)
    value = db.TextProperty()
    
    def __str__(self):
        return str(self.value)
    
    def undo(self):
        if self.older():
            oldValue = self.older()
            if oldValue:
                oldValue.owner = self.owner
                oldValue.put()
        Cache.delete(self.owner, self.language, type = LocalizedTextValue)
        super(LocalizedTextValue, self).delete()
        
    def older(self):
        oldValue = None
        if getattr(self,'_values', None):
            oldValue = self._values.get()
        return oldValue
    
    def newer(self):
        if self.owner:
            if isinstance(self.owner, LocalizedTextValue):
                return self.owner
        return None                
    
    def delete(self):
        Cache.delete(self.owner, self.language, type = LocalizedTextValue)
        if getattr(self,'_values', None):
            textValue = self._values.get()
            if textValue:
                textValue.delete()
        super(LocalizedTextValue, self).delete()        
        
    def put(self):
        super(LocalizedTextValue,self).put()
        Cache.set(self.owner, self.language, value = self, type = LocalizedTextValue)        
    
    def text(self):
        return str(self)
    
    def html(self):
        return "<span " + self.html_attr() + ">" + self.text() + "</span>"
    def html_attr(self):
        return "data-text-id=\"" + str(self.owner.key()) + "\""
    
    def __call__(self):
        return self.current()                  
    
    def __init__(self, *args, **kwargs):  
        super(LocalizedTextValue, self).__init__(*args, **kwargs)
        